import type {
  ColorSpecification,
  DataDrivenPropertyValueSpecification,
} from 'mapbox-gl';
import type { Mapless } from '..';
import type { IdHubType } from '../core/IdHub';
import IdHub from '../core/IdHub';
import type { Handler } from '../core/Listener';
import { EmitManager } from '../core/manager';
import type { ManagerOptions, Station, StationManagerEvents } from '../index.d';

type OldStationIdHubType = IdHubType & {
  detailSelectedLayerId: string;
  detailLayerId: string;
  simpleSelectedLayerId: string;
  simpleSensorLayerId: string;
  simpleLayerId: string;
  sourceId: string;
};

const stateColorRule: DataDrivenPropertyValueSpecification<ColorSpecification> =
  [
    'case',
    ['==', ['get', 'state'], 'busy'],
    'rgba(250, 173, 20, 0.8)',
    ['==', ['get', 'state'], 'fault'],
    'rgba(245, 34, 45, 0.8)',
    ['==', ['get', 'state'], 'offline'],
    'rgba(151, 151, 151, 0.8)',
    ['==', ['get', 'state'], 'disable'],
    'rgba(151, 151, 151, 0.8)',
    'rgba(82, 196, 26, 0.8)',
  ];

/**
 * TODO icon基于128*128尺寸计算,要动态;small-size为16*16
 * TODO 不同category放在不同图层
 * TODO 控制图层显示隐藏，或者外部工具根据不同类型设置Visible（display）
 * TODO OldStationManager将被更名为StationManager
 */
class OldStationManager extends EmitManager<
  StationManagerEvents,
  OldStationIdHubType
> {
  private stations: Station[] = [];

  public selectable = true;
  public displayCategoryFilterFunc: ((s: Station) => boolean) | undefined =
    undefined;

  getStations() {
    return this.stations;
  }

  clearSelected() {
    if (this.selectable) {
      this.stations.forEach((s) => {
        s.selected = false;
      });
      this.drawStations(this.stations);
    }
  }

  constructor(mapless: Mapless, options?: ManagerOptions) {
    super(mapless, options, 'station');
    this.onInitialized();

    this.setupClickHandler();
    this.setupHoverHandler();
  }

  override createIdHub(_idHub?: IdHubType) {
    const newHub = new IdHub({
      layers: {
        detailSelectedLayerId: 'dzmap-station-detail-selected-layer',
        detailLayerId: 'dzmap-station-detail-layer',
        simpleSelectedLayerId: 'dzmap-station-simple-selected-layer',
        simpleSensorLayerId: 'dzmap-station-simple-sensor-layer',
        simpleLayerId: 'dzmap-station-simple-layer',
      },
      sources: {
        sourceId: 'dzmap-station-source',
      },
    }) as OldStationIdHubType;
    super.createIdHub(newHub);
  }

  override initLayers() {
    if (!this.mapless) return;
    const dsource = this.idHub?.sourceId;
    this.mapless.addEmptySource(dsource);
    this.mapless.addLayer({
      id: this.idHub?.detailSelectedLayerId,
      type: 'circle',
      source: dsource,
      minzoom: 12,
      // filter: ['==', ['get', 'selected'], true],
      paint: {
        'circle-radius': [
          'case',
          ['==', ['get', 'category'], 'sensor'],
          18,
          24,
        ], // 保持与普通图标相同大小
        'circle-color': [
          'case',
          ['==', ['get', 'selected'], true],
          'rgba(0, 120, 255, 0.3)',
          'rgba(0, 120, 255, 0.1)',
        ], // 半透明蓝色
        'circle-stroke-width': [
          'case',
          ['==', ['get', 'selected'], true],
          3,
          1,
        ], // 增加边框宽度
        'circle-stroke-color': '#1890ff', // 蓝色边框
      },
    });
    this.mapless.addLayer({
      id: this.idHub?.detailLayerId,
      type: 'symbol',
      source: dsource,
      minzoom: 12,
      layout: {
        'icon-image': [
          'concat',
          // ['get', 'type'],
          // '',
          ['get', 'category'],
          '_',
          ['coalesce', ['get', 'state'], 'normal'],
        ],
        'icon-rotate': ['get', 'azimuth'],
        'icon-size': [
          'case',
          ['==', ['get', 'category'], 'sensor'],
          0.25,
          ['==', ['get', 'selected'], true],
          0.32,
          0.3,
        ],
        'text-field': ['get', 'name'],
        'text-font': ['Open Sans Regular', 'Arial Unicode MS Regular'],
        'text-size': ['case', ['==', ['get', 'selected'], true], 14, 12],
        'text-offset': [0, 2.0],
        'text-anchor': 'top',
        'icon-allow-overlap': true, // 允许图标重叠
        'text-allow-overlap': true, // 允许文字重叠
        'icon-ignore-placement': true, // 忽略图标位置冲突
        'text-ignore-placement': true, // 忽略文字位置冲突
      },
      paint: {
        'text-color': stateColorRule,
        'text-halo-color': 'rgba(255, 255, 255, 0.3)',
        'text-halo-width': 1, // 阴影宽度
        'text-halo-blur': 0, // 阴影模糊度
      },
    });
    this.mapless.addLayer({
      id: this.idHub?.simpleSelectedLayerId,
      type: 'circle',
      source: dsource,
      maxzoom: 12,
      filter: ['==', ['get', 'selected'], true],
      paint: {
        'circle-radius': ['case', ['==', ['get', 'category'], 'sensor'], 9, 12], // sensor图标为7，其他为9
        'circle-color': 'rgba(0, 120, 255, 0.2)',
        'circle-stroke-width': 1,
        'circle-stroke-color': '#1890ff', // 蓝色边框
      },
    });
    this.mapless.addLayer({
      id: this.idHub?.simpleLayerId,
      type: 'circle',
      source: dsource,
      maxzoom: 12,
      filter: ['!', ['==', ['get', 'category'], 'sensor']],
      paint: {
        'circle-radius': ['case', ['==', ['get', 'category'], 'sensor'], 7, 9], // sensor图标为7，其他为9
        'circle-color': stateColorRule,
        'circle-stroke-width': 1,
        'circle-opacity': [
          'case',
          ['==', ['get', 'category'], 'sensor'],
          0.5,
          1,
        ],
      },
    });
    this.mapless.addLayer({
      id: this.idHub?.simpleSensorLayerId,
      type: 'symbol',
      source: dsource,
      filter: ['==', ['get', 'category'], 'sensor'],
      maxzoom: 12,
      layout: {
        'icon-image': [
          'concat',
          // ['get', 'type'],
          // '',
          ['get', 'category'],
          '_',
          ['coalesce', ['get', 'state'], 'normal'],
        ],
        'icon-rotate': ['get', 'azimuth'],
        'icon-size': 0.1,
        'icon-allow-overlap': true, // 允许图标重叠
        'icon-ignore-placement': true, // 忽略图标位置冲突
      },
    });
  }

  getFeatures = (stations: Station[]) => {
    return stations
      .filter((station) => {
        if (station.category === 'CityCenter') return false;
        if (this.displayCategoryFilterFunc) {
          return this.displayCategoryFilterFunc(station);
        }
        if (this._showSelectedOnly) {
          return station.selected;
        }
        return station.display !== false;
      })
      .map((station) => ({
        type: 'Feature' as const,
        geometry: {
          type: 'Point' as const,
          coordinates: [station.longitude, station.latitude],
        },
        properties: {
          id: station.id,
          type: station.type,
          category: station.category?.toLowerCase(),
          name: station.name,
          state: station.state?.toLowerCase(),
          selected: station.selected,
          azimuth: station.azimuth || 0,
        },
      }));
  };

  drawStations = (stations: Station[]) => {
    // 缓存当前stations
    this.stations = stations;
    // 准备数据源
    const features = this.getFeatures(stations);
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features,
    });
  };

  updateStations(stations: Station[]) {
    // 更新缓存数据
    stations.forEach((updatedStation) => {
      const index = this.stations.findIndex((s) => s.id === updatedStation.id);
      if (index !== -1) {
        this.stations[index] = { ...this.stations[index], ...updatedStation };
      }
    });
    // 更新地图数据源
    const features = this.getFeatures(this.stations);
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features,
    });
  }

  updateSelectedList(
    stationsIds: (string | undefined)[],
    validateSelectedable = true,
  ) {
    if (validateSelectedable) {
      if (!this.selectable) return;
    }
    // 更新缓存数据
    this.stations.forEach((s) => {
      s.selected = stationsIds.includes(s.id);
    });
    const features = this.getFeatures(this.stations);
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features,
    });
  }

  private _showSelectedOnly = false;
  // TODO setShowSelectedOnly
  setShowSelectedOnly = (showSelectedOnly: boolean) => {
    this._showSelectedOnly = showSelectedOnly;
    if (!this.map) return;
    this.stations.forEach((s) => {
      s.display = showSelectedOnly ? s.selected : true;
    });
    const features = this.getFeatures(this.stations);
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features,
    });
  };

  override fitBounds = (useSelected = false, padding = 20) => {
    let ss = useSelected
      ? this.stations.filter((s) => s.selected)
      : this.stations;
    if (ss.length <= 0) {
      ss = this.stations;
    }
    const coordinates = ss.map((s) => {
      return [s.longitude, s.latitude] as [number, number];
    });
    if (coordinates.length > 0) {
      this.mapless?.fitBounds(coordinates, padding);
    }
  };

  emitEvent = (
    type: 'stationsSelected',
    data: Station[],
    sourceName?: string,
  ) => {
    if (!this.selectable) return;
    this.emit(type, { stations: data, sourceName });
  };

  private setupClickHandler() {
    const clickHandler = (e: mapboxgl.MapMouseEvent) => {
      if (!this.selectable) return;

      const feature = e.features?.[0];
      if (feature) {
        const curr = this.stations.find(
          (station) => station.id === feature.properties?.id,
        );
        if (curr) {
          if (e.originalEvent.ctrlKey || e.originalEvent.metaKey) {
            // Ctrl/Command键按下时切换选中状态
            curr.selected = !curr.selected;
            const selectedStations = this.stations.filter((s) => s.selected);
            this.emit('stationsSelected', {
              stations: selectedStations,
              sourceName: 'StationManager',
            });
          } else {
            // 普通点击时单选
            this.stations.forEach((s) => {
              s.selected = false;
            });
            curr.selected = true;
            this.emit('stationsSelected', {
              stations: [curr],
              sourceName: 'StationManager',
            });
          }
          const features = this.getFeatures(this.stations);
          this.mapless?.setData(this.idHub?.sourceId, {
            type: 'FeatureCollection',
            features,
          });
        }
      }
    };
    const layers = [
      this.idHub?.detailLayerId,
      this.idHub?.simpleLayerId,
      this.idHub?.simpleSensorLayerId,
    ];
    this._listener?.addIdList('click', layers, clickHandler as Handler);
  }

  private setupHoverHandler() {
    const enterHnadler = (e: mapboxgl.MapMouseEvent) => {
      const feature = e.features?.[0];
      if (feature) {
        this.mapless?.setCursor('pointer');
      }
    };
    const leaveHandler = () => {
      this.mapless?.setCursor('');
    };
    const layers = [
      this.idHub?.detailLayerId,
      this.idHub?.simpleLayerId,
      this.idHub?.simpleSensorLayerId,
    ];
    this._listener?.addIdList('mouseenter', layers, enterHnadler as Handler);
    this._listener?.addIdList('mouseleave', layers, leaveHandler as Handler);
  }

  override destroy = () => {
    super.destroy();
    this.stations = [];
  };
}

export default OldStationManager;

export const attachOldStation = (mapless: Mapless | undefined, name?: string) =>
  mapless?.use(OldStationManager, name);
export const getOldStation = (mapless: Mapless | undefined, name?: string) =>
  mapless?.get(OldStationManager, name);
export const detachOldStation = (mapless: Mapless | undefined, name?: string) =>
  mapless?.unuse(OldStationManager, name);
